package business.global.pk.ddz;

import business.ddz.c2s.cclass.DDZ_define;
import business.ddz.c2s.iclass.*;
import business.ddz.c2s.cclass.DDZRoomSetInfo;
import business.global.room.RoomRecordMgr;
import business.global.room.base.AbsRoomPos;
import business.global.room.base.AbsRoomPosMgr;
import business.global.room.base.RoomTyepImpl;
import business.global.room.pk.PockerRoom;
import cenum.ChatType;
import cenum.ClassType;
import cenum.RoomTypeEnum;
import cenum.room.GaoJiTypeEnum;
import cenum.room.RoomState;
import com.ddm.server.common.CommLogD;
import com.ddm.server.common.utils.JsonUtil;
import com.ddm.server.websocket.def.ErrorCode;
import com.ddm.server.websocket.handler.requset.WebSocketRequest;
import com.google.gson.Gson;
import core.network.http.proto.SData_Result;
import jsproto.c2s.cclass.BaseSendMsg;
import jsproto.c2s.cclass.pk.PKRoom_Record;
import jsproto.c2s.cclass.pk.PKRoom_RecordPosInfo;
import jsproto.c2s.cclass.room.BaseRoomConfigure;
import jsproto.c2s.cclass.room.GetRoomInfo;
import jsproto.c2s.cclass.room.RoomPosInfo;
import jsproto.c2s.iclass.S_GetRoomInfo;
import jsproto.c2s.iclass.room.SBase_Dissolve;
import jsproto.c2s.iclass.room.SBase_PosLeave;

import java.util.ArrayList;
import java.util.List;
import business.ddz.c2s.cclass.DDZ_define.DDZ_FengDing;
import business.ddz.c2s.cclass.DDZ_define.DDZ_ThreeZone;
import business.ddz.c2s.cclass.DDZ_define.DDZ_FourZone;
import business.ddz.c2s.cclass.DDZ_define.DDZ_KeXuanWanFa;
import org.apache.commons.collections.CollectionUtils;

/**
 * 安岳跑的快游戏房间
 */
public class DDZRoom extends PockerRoom {
    public CDDZ_CreateRoom cfg;// 开房配置
    private DDZConfigMgr configMgr = new DDZConfigMgr();
    protected int landowner = -1;//本局地主位置
    private boolean isOpenStartGame = false;//还没明牌开始
    private int firstStartOpenPos = -1;// 第一个明牌开始的人
    private int firstOpenPos = -1;// 第一个明牌的人
    private int lastWinPos = -1;// 最后第一个出完牌的人
    public boolean isEnd = false;

    protected DDZRoom(BaseRoomConfigure<CDDZ_CreateRoom> baseRoomConfigure, String roomKey, long ownerID) {
        super(baseRoomConfigure, roomKey, ownerID);
        initShareBaseCreateRoom(CDDZ_CreateRoom.class, baseRoomConfigure);
        this.cfg = (CDDZ_CreateRoom) baseRoomConfigure.getBaseCreateRoom();
    }

    @Override
    public String dataJsonCfg() {
        // 获取房间配置
        return new Gson().toJson(this.getRoomCfg());
    }

    /**
     * 获取房间配置
     *
     * @return
     */
    public CDDZ_CreateRoom getRoomCfg() {
        if (this.cfg == null) {
            initShareBaseCreateRoom(CDDZ_CreateRoom.class, getBaseRoomConfigure());
            return (CDDZ_CreateRoom) getBaseRoomConfigure().getBaseCreateRoom();
        }
        return this.cfg;
    }

    /**
     * 房间内每个位置信息 管理器
     */
    @Override
    public AbsRoomPosMgr initRoomPosMgr() {
        return new DDZRoomPosMgr(this);
    }

    @Override
    public void startNewSet() {
        // 更新连续托管局数
        for(int i = 0; i < getPlayerNum(); i++){
            DDZRoomPos DDZRoomPos = (DDZRoomPos)getRoomPosMgr().getPosByPosID(i);
            if(DDZRoomPos.isTrusteeship()){ // 托管
                DDZRoomPos.addTuoGuanSetCount();
            }
        }
        this.setCurSetID(this.getCurSetID() + 1);
        // 每个位置，清空准备状态
        this.getRoomPosMgr().clearGameReady();
        this.createSet();
        // 通知局数变化
        this.getRoomTyepImpl().roomSetIDChange();
        this.setAutoDismiss(false);
    }

    @Override
    public void cancelTrusteeship(AbsRoomPos pos) {
        ((DDZRoomSet) this.getCurSet()).roomTrusteeship(pos.getPosID());
    }

    @Override
    public boolean isCanChangePlayerNum() {
        return false;
    }

    @Override
    public <T> T getCfg() {
        return (T) getRoomCfg();
    }

    /**
     * 清空当前局，创建新小局
     */
    public void createSet() {
        if (null != this.getCurSet()) {
            this.getCurSet().clear();
            this.setCurSet(null);
        }
        //清理开始标志
        ((DDZRoomPosMgr)this.getRoomPosMgr()).clearBeginFlag();
        setFirstOpenPos(0,true);
        this.setCurSet(new DDZRoomSet(this));
    }

    @Override
    public void roomTrusteeship(int pos) {
        if (getCurSet() != null && ((DDZRoomSet) getCurSet()).getCurRound() != null) {
            ((DDZRoomSet) this.getCurSet()).roomTrusteeship(pos);
        }
    }

    @Override
    public void setEndRoom() {
        if (null != this.getCurSet()) {
            if (getHistorySet().size() > 0) {
                // 增加房局记录
                RoomRecordMgr.getInstance().add(this);
                this.getRoomPosMgr().notify2All(SDDZ_RoomEnd.make(this.getPKRoomRecordInfo()));
                refererReceiveList();
            }
        }
    }

    /**
     * 构建房间回放返回给客户端
     *
     * @return 通知结构体
     */
    public PKRoom_Record getPKRoomRecordInfo() {
        PKRoom_Record pkRoom_record = new PKRoom_Record();
        pkRoom_record.setCnt = this.getHistorySetSize();
        pkRoom_record.recordPosInfosList = this.getRecordPosInfoList();
        pkRoom_record.roomID = this.getRoomID();
        pkRoom_record.endSec = this.getGameRoomBO().getEndTime();
        pkRoom_record.roomKey = getRoomKey();
        return pkRoom_record;
    }

    /**
     * 获取位置输赢信息
     *
     * @return
     */
    @Override
    protected List<PKRoom_RecordPosInfo> getRecordPosInfoList() {
        List<PKRoom_RecordPosInfo> sRecord = new ArrayList<>();
        for (int i = 0; i < this.getPlayerNum(); i++) {

            DDZRoomPos roomPos = (DDZRoomPos) this.getRoomPosMgr().getPosByPosID(i);
            PKRoom_RecordPosInfo posInfo = roomPos.initAndReturnResult(new PKRoom_RecordPosInfo());

            posInfo.flatCount = roomPos.getFlat();
            posInfo.loseCount = roomPos.getLose();
            posInfo.winCount = roomPos.getWin();

            posInfo.point = roomPos.getPoint();
            posInfo.pos = i;
            posInfo.pid = roomPos.getPid();
            posInfo.isLandowner = ((DDZRoomSet)getCurSet()).landowner == i;
            posInfo.setSportsPoint(roomPos.sportsPoint());
            sRecord.add(posInfo);
        }
        return sRecord;
    }

    public DDZConfigMgr getConfigMgr() {
        return configMgr;
    }

    /**
     * 获取房间人数
     */
    @Override
    public int getPlayerNum() {
        return this.getRoomCfg().getPlayerNum();
    }

    @Override
    public void clearEndRoom() {
        super.clear();
        this.configMgr = null;
        this.cfg = null;
    }

    @Override
    public int getTimerTime() {
        return 500;
    }

    @Override
    public int getPlayingCount() {
        return this.getPlayerNum();
    }

    public boolean isGodCard() {
        return this.getConfigMgr().isGodCard();
    }

    /**
     * 打牌
     *
     * @param request
     * @param opCard
     */
    public void onOpCard(WebSocketRequest request, CDDZ_OpCard opCard) {
        try {
            lock();
            DDZRoomSet set = (DDZRoomSet) this.getCurSet();
            if (null == set) {
                request.error(ErrorCode.NotAllow, "onOpCard not set room:" + opCard.roomID);
                return;
            }
            DDZRoomSetRound round = set.getCurRound();
            if (null == round) {
                request.error(ErrorCode.NotAllow, "onOpCard not round room:" + opCard.roomID);
                return;
            }
            round.onOpCard(request, opCard);
        }catch (Exception e){
            CommLogD.error(e.getMessage());
        }finally {
            unlock();
        }
    }

    /**
     * 神牌消息
     *
     * @param msg
     * @param pid
     */
    @Override
    public boolean godCardMsg(String msg, long pid) {
        return false;
    }

    @Override
    public BaseSendMsg Trusteeship(long roomID, long pid, int pos, boolean trusteeship) {
        return SDDZ_Trusteeship.make(roomID, pid, pos, trusteeship);
    }

    @Override
    public BaseSendMsg PosLeave(SBase_PosLeave posLeave) {
        return SDDZ_PosLeave.make(posLeave);
    }

    @Override
    public BaseSendMsg LostConnect(long roomID, long pid, boolean isLostConnect, boolean isShowLeave) {
        return SDDZ_LostConnect.make(roomID, pid, isLostConnect, isShowLeave);
    }

    @Override
    public BaseSendMsg PosContinueGame(long roomID, int pos) {
        return SDDZ_PosContinueGame.make(roomID, pos);
    }

    @Override
    public BaseSendMsg PosUpdate(long roomID, int pos, RoomPosInfo posInfo, int custom) {
        return SDDZ_PosUpdate.make(roomID, pos, posInfo, custom);
    }

    @Override
    public BaseSendMsg PosReadyChg(long roomID, int pos, boolean isReady) {
        return SDDZ_PosReadyChg.make(roomID, pos, isReady);
    }

    @Override
    public BaseSendMsg Dissolve(SBase_Dissolve dissolve) {
        return SDDZ_Dissolve.make(dissolve);
    }

    @Override
    public BaseSendMsg StartVoteDissolve(long roomID, int createPos, int endSec) {
        return SDDZ_StartVoteDissolve.make(roomID, createPos, endSec);
    }

    @Override
    public BaseSendMsg PosDealVote(long roomID, int pos, boolean agreeDissolve, int endSec) {
        return SDDZ_PosDealVote.make(roomID, pos, agreeDissolve);
    }

    @Override
    public BaseSendMsg Voice(long roomID, int pos, String url) {
        return SDDZ_Voice.make(roomID, pos, url);
    }

    @Override
    public BaseSendMsg XiPai(long roomID, long pid, ClassType cType) {
        return SDDZ_XiPai.make(roomID, pid, cType);
    }

    @Override
    public BaseSendMsg ChatMessage(long pid, String name, String content, ChatType type, long toCId, int quickID) {
        return SDDZ_ChatMessage.make(pid, name, content, type, toCId, quickID);
    }

    @Override
    public <T> BaseSendMsg RoomRecord(List<T> records) {
        return SDDZ_RoomRecord.make(records);
    }

    @Override
    public BaseSendMsg ChangePlayerNum(long roomID, int createPos, int endSec, int playerNum) {
        return SDDZ_ChangePlayerNum.make(roomID, createPos, endSec, playerNum);
    }

    @Override
    public BaseSendMsg ChangePlayerNumAgree(long roomID, int pos, boolean agreeChange) {
        return SDDZ_ChangePlayerNumAgree.make(roomID, pos, agreeChange);
    }

    @Override
    public BaseSendMsg ChangeRoomNum(long roomID, String roomKey, int createType) {
        return SDDZ_ChangeRoomNum.make(roomID, roomKey, createType);
    }

    @Override
    public GetRoomInfo getRoomInfo(long pid) {
        S_GetRoomInfo ret = new S_GetRoomInfo();
        // 设置房间公共信息
        this.getBaseRoomInfo(ret);
        if (null != this.getCurSet()) {
            ret.setSet(this.getCurSet().getNotify_set(pid));
        } else {
            ret.setSet(new DDZRoomSetInfo());
        }
        return ret;
    }

//    @Override
    public RoomTyepImpl newUnionRoom() {
        return new DDZUnionRoom(this);
    }

    /**
     * 继续游戏
     *
     * @param pid 用户ID
     */
    @SuppressWarnings("rawtypes")
    @Override
    public SData_Result continueGame(long pid) {
        try {
            lock();
            if (!RoomState.Playing.equals(this.getRoomState())) {
                // 房间不处于游戏阶段
                return SData_Result.make(ErrorCode.NotAllow, "continueGame RoomState Playing :{%s}",
                        this.getRoomState());
            }
            AbsRoomPos roomPos = this.getRoomPosMgr().getPosByPid(pid);
            if (null == roomPos) {
                // 找不到通过pid获取玩家信息
                return SData_Result.make(ErrorCode.NotAllow, "continueGame null == roomPos");
            }
            if (roomPos.isTrusteeship()) {
                // 如果玩家处于托管状态则，不能手动点击继续游戏。
                return SData_Result.make(ErrorCode.Is_Trusteeship, "continueGame isTrusteeship:{%s}",
                        roomPos.isTrusteeship());
            }
            SData_Result result = unionContinueGame(roomPos);
            if (!ErrorCode.Success.equals(result.getCode())) {
                return SData_Result.make(result.getCode(), result.getMsg());
            }
            roomPos.setContinue();
            roomPos.setTimeSec(0);
            return SData_Result.make(ErrorCode.Success);
        } finally {
            unlock();
        }
    }

    /**
     * 联赛继续游戏
     *
     * @return
     */
    private SData_Result unionContinueGame(AbsRoomPos roomPos) {
        /*if (RoomTypeEnum.UNION.equals(this.getRoomTypeEnum())) {
            DDZUnionRoom hbmjUnionRoom = (DDZUnionRoom) this.getRoomTyepImpl();
            return hbmjUnionRoom.unionContinueGame(roomPos);
        } else {
            return SData_Result.make(ErrorCode.Success);
        }*/
        return SData_Result.make(ErrorCode.Success);
    }

    /**
     * 立即开始
     *
     * @return
     */
    @Override
    public boolean atOnceStartGame() {
        return true;
    }

    @Override
    public void RobotDeal(int pos) {
        ((DDZRoomSet) this.getCurSet()).roomTrusteeship(pos);
    }

    /**
     * 房主是否需要准备
     *
     * @return
     */
    @Override
    public boolean ownerNeedReady() {
        return true;
    }

    /**
     * 存在有玩家离开、踢出清空所有玩家准备状态
     * @return T: 清空,F:不清空
     */
    public boolean existLeaveClearAllPosReady() {
        return true;
    }

    /**
     *
     * 30秒未准备自动退出
     * @return
     */
    @Override
    public boolean is30SencondTimeOut() {
        return checkGaoJiXuanXiang(GaoJiTypeEnum.SECOND_TIMEOUT_30);
    }

    /**
     * 获取封顶倍数
     * @return
     */
    public int getFengDing(){
        return DDZ_FengDing.getFengDing(getRoomCfg().dizhufengding);
    }

    /**
     * 是否是3带1
     * @return
     */
    public boolean isThreeZoneWithA(){
        return CollectionUtils.isNotEmpty(getRoomCfg().sandai) && getRoomCfg().sandai.contains(DDZ_ThreeZone.ThreeZoneWithA.value());
    }

    /**
     * 是否是3带一对
     * @return
     */
    public boolean isThreeZoneWithPairs(){
        return CollectionUtils.isNotEmpty(getRoomCfg().sandai) && getRoomCfg().sandai.contains(DDZ_ThreeZone.ThreeZoneWithPairs.value());
    }

    /**
     * 是否是4带2
     * @return
     */
    public boolean isFourWithTwo(){
        return CollectionUtils.isNotEmpty(getRoomCfg().sidai) && getRoomCfg().sidai.contains(DDZ_FourZone.FourWithTwo.value());
    }

    /**
     * 是否是4带2对
     * @return
     */
    public boolean isFourWithTwoPairs(){
        return CollectionUtils.isNotEmpty(getRoomCfg().sidai) && getRoomCfg().sidai.contains(DDZ_FourZone.FourWithTwoPairs.value());
    }

    /**
     * 是否是4带1
     * @return
     */
    public boolean isFourWithA(){
        return CollectionUtils.isNotEmpty(getRoomCfg().sidai) && getRoomCfg().sidai.contains(DDZ_FourZone.FourWithA.value());
    }

    /**
     * 是否是4带1对
     * @return
     */
    public boolean isFourWithAPairs(){
        return CollectionUtils.isNotEmpty(getRoomCfg().sidai) && getRoomCfg().sidai.contains(DDZ_FourZone.FourWithAPairs.value());
    }

    /**
     * 是否能铭牌
     * @return
     */
    public boolean isCanOpenCard(){
        return !getRoomCfg().getKexuanwanfa().contains(DDZ_KeXuanWanFa.DisableOpenCard.value());
    }

    /**
     * 是否自动准备
     * @return
     */
    @Override
    public boolean autoReadyGame() {
        return getRoomCfg().getKexuanwanfa().contains(DDZ_KeXuanWanFa.AutoReady.value());
    }

    /**
     * 不能翻倍
     * @return
     */
    public boolean isDisAddDouble(){
        return getRoomCfg().getKexuanwanfa().contains(DDZ_KeXuanWanFa.DisAddDouble.value());
    }

    public void setOpenStartGame(boolean openStartGame) {
        isOpenStartGame = openStartGame;
    }

    public boolean isOpenStartGame() {
        return isOpenStartGame;
    }

    /**
     * 更新首个明牌开始的人
     * @param firstStartOpenPos
     */
    public void setFirstStartOpenPos(int firstStartOpenPos,boolean isClear) {
        if(isClear){
            this.firstStartOpenPos = -1;
        }else{
            if(this.firstStartOpenPos <0){
                this.firstStartOpenPos = firstStartOpenPos;
            }
        }
    }

    public int getFirstStartOpenPos() {
        return firstStartOpenPos;
    }

    /**
     * 跟新首个明牌的人
     * @param firstOpenPos
     */
    public void setFirstOpenPos(int firstOpenPos,boolean isClear) {
        if(isClear){
            this.firstOpenPos = -1;
        }else{
            if(this.firstOpenPos <0){
                this.firstOpenPos = firstOpenPos;
            }
        }
    }

    public int getFirstOpenPos() {
        return firstOpenPos;
    }

    /**
     * 是否需要解散次数
     * @return
     */
    @Override
    public boolean needDissolveCount(){
        return true;
    }

    /**
     * 获取解散次数
     * @return
     */
    @Override
    public int getJieShanShu(){
        return 3;
    }


    /**
     * 是否小局自动解散
     *
     * @return boolean
     */
    public boolean isSetAutoJieSan() {
        return this.getBaseRoomConfigure().getBaseCreateRoom().getFangjian().contains(DDZ_define.DDZGameRoomConfigEnum.SetAutoJieSan.ordinal());
    }

    /**
     * 是否小局2自动解散
     *
     * @return boolean
     */
    public boolean isSetAutoJieSan2() {
        return this.getBaseRoomConfigure().getBaseCreateRoom().getFangjian().contains(DDZ_define.DDZGameRoomConfigEnum.SetAutoJieSan2.ordinal());
    }

    /**
     * 是否自动过牌
     * @return
     */
    public boolean autoPass() {
        return getRoomCfg().getKexuanwanfa().contains(DDZ_KeXuanWanFa.ZiDongGuoPai.value());
    }

    /**
     * 是否上局先出完牌先叫
     * @return
     */
    public boolean shangJuXianJiao() {
        return getRoomCfg().getKexuanwanfa().contains(DDZ_KeXuanWanFa.ShangJuXianJiao.value());
    }


    /**
     * 双王或4个2必叫
     * @return
     */
    public boolean shuangWang() {
        return getRoomCfg().getKexuanwanfa().contains(DDZ_KeXuanWanFa.ShuangWangBiJiao.value());
    }

    /**
     * 上局优先出完牌的玩家
     * @param lastWinPos
     */
    public void setLastWinPos(int lastWinPos) {
        this.lastWinPos = lastWinPos;
    }

    /**
     * 上局优先出完牌的玩家
     * @return
     */
    public int getLastWinPos() {
        return lastWinPos;
    }

    /**
     * 竞技点能否低于零
     * @returnx
     */
    @Override
    public boolean isRulesOfCanNotBelowZero(){
        return getRoomCfg().getKexuanwanfa().contains(DDZ_KeXuanWanFa.DDZ_WANFA_NOTBELOWZERO.value());
    }

    /**
     * 只能赢当前身上分
     * @return
     */
    @Override
    public boolean isOnlyWinRightNowPoint(){
        return getRoomCfg().getKexuanwanfa().contains(DDZ_KeXuanWanFa.DDZ_WANFA_OnlyWinRightNowPoint.value());
    }

    @Override
    public boolean isEnd(){
        return isEnd;
    }

    /**
     * 是否禁止语音
     * @return
     */
    @Override
    public boolean isDisAbleVoice(){
        return checkGaoJiXuanXiang(GaoJiTypeEnum.DISABLE_VOICE);
    }

    /**
     * 是否底牌不翻倍
     * @return
     */
    public boolean isNotCoverDouble(){
        return getRoomCfg().getKexuanwanfa().contains(DDZ_KeXuanWanFa.CoverNotDouble.value());
    }

    /**
     * 10秒未准备自动退出
     *
     * @return
     */
    public boolean is10SencondTimeOut() {
        return this.getRoomCfg().getGaoji().contains(GaoJiTypeEnum.SECOND_TIMEOUT_10.ordinal());
    }

    /**
     * 5秒未准备自动退出
     *
     * @return
     */
    public boolean is5SencondTimeOut() {
        return this.getRoomCfg().getGaoji().contains(DDZ_define.GaoJiTypeEnum.SECOND_TIMEOUT_5.ordinal());
    }
}
